home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / utils / lookup.c < prev    next >
C/C++ Source or Header  |  1995-04-19  |  7KB  |  339 lines

  1. /*
  2.  *    lookup.c
  3.  *
  4.  *
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <memory.h>
  11. #include <ctype.h>
  12. #include <errno.h>
  13. #include <fcntl.h>
  14. #include <assert.h>
  15. #ifdef unix
  16. #include <unistd.h>
  17. /*#include <strerror.h>*/
  18. #define strnicmp  strncasecmp
  19. #else
  20. #include <io.h>
  21. #endif
  22. #include "rockridg.h"
  23. #include "datadef.h"
  24.  
  25. #ifndef O_BINARY
  26. #define O_BINARY 0
  27. #endif
  28.  
  29. static void Read(int fd, void *buf, int n, int swap);
  30. #if 0
  31. static void _Read(int fd, void *buf, int n, int swap, int line, char *file);
  32. #define  Read(fd, buf, n, swap) _Read((fd), (buf), (n), (swap), __LINE__, __FILE__)
  33. #endif
  34.  
  35. #ifdef unix
  36. static const char datafile[] = "utils/lookup.dat";
  37. #else
  38. static const char datafile[] = "/utils/lookup.dat";
  39. #endif
  40. static char word[256];
  41. static struct file_header hdr;
  42. static long rehash6;
  43. static long rehash16;
  44. static int fd;
  45.  
  46. static long
  47. hash2(const unsigned char *s) {
  48.   unsigned long h, g, r;
  49.   int c;
  50.   int i;
  51.  
  52.   r = h = ((long) s[0] << 16) + (s[1] << 8);
  53.   for (i = 0; s[i] != 0; ++i) {
  54.       h += ((long) s[i] << i) + s[i];
  55.       h ^= h >> i;
  56.   }
  57.   while ((c = *s++) != '\0') {
  58.       h <<= 4;
  59.       h += c;
  60.       g = h & 0xf0000000;
  61.       h ^= g;
  62.       h ^= (g >> 24);
  63.       r ^= h;
  64.   }
  65.   rehash6 = r % 61;
  66.   rehash16 = r % 65521;
  67.   return h % hdr.hash_prime;
  68. }
  69.  
  70. static int
  71. search_file(const char *filename) {
  72.     FILE *fp;
  73.     int rv;
  74.     static char line[257];
  75.     char *s;
  76.     int lc, uc, len;
  77.  
  78.  
  79. /*    fprintf(stderr, "searching file %s\n", filename); */
  80.  
  81.     lc = *word;
  82.     if (islower(lc)) {
  83.         uc = lc + 'A' - 'a';
  84.     } else {
  85.         uc = lc;
  86.     }
  87.     len = strlen(word);
  88.     if ((fp = fopen(filename, "rt")) == NULL) {
  89.         fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
  90.         return 0;
  91.     }
  92.     rv = 0;
  93.     while (fgets(line, 256, fp) != NULL) {
  94.     line[255] = '\n';
  95.     line[256] = '\0';
  96.         for (s = line; *s != 0; ++s) {
  97.             if (*s == lc || (*s == uc && isupper(*s))) {
  98.                 if (strnicmp(s, word, len) == 0) {
  99.                     ++rv;
  100.                     printf("%s: %s", filename, line);
  101.             break;
  102.                 }
  103.             }
  104.         }
  105.     }
  106.     fclose(fp);
  107.     return rv;
  108. }
  109.  
  110. static char *
  111. lookup_dir(int n) {
  112.     static char path[1024];
  113.     unsigned char buf[300];
  114.     unsigned char *p;
  115.     short dir_num;
  116.     long x;
  117.  
  118.     if (n == 0) {
  119.         path[0] = '\0';
  120.         return path;
  121.     }
  122.     lseek(fd, hdr.dir_table_offset + n * sizeof(long), SEEK_SET);
  123.     Read(fd, &x, sizeof(x), 1);
  124.     lseek(fd, x, SEEK_SET);
  125.     Read(fd, buf, sizeof(buf), 0);
  126.     dir_num = buf[0] + (buf[1] << 8);
  127.     p = lookup_dir(dir_num);
  128.     strcat(p, "/");
  129.     strcat(p, buf + 2);
  130.     return p;
  131. }
  132.  
  133. static char *
  134. lookup_filename(long n) {
  135.     unsigned char buf[300];
  136.     unsigned char *p;
  137.     short dir_num;
  138.  
  139.     lseek(fd, n, SEEK_SET);
  140.     Read(fd, buf, sizeof(buf), 0);
  141.     dir_num = buf[0] + (buf[1] << 8);
  142.     p = lookup_dir(dir_num);
  143.     strcat(p, "/");
  144.     strcat(p, buf + 2);
  145.     return p;
  146. }
  147.  
  148. static int
  149. search_block(int block) {
  150.     int rv, i;
  151.     long *p;
  152.     long b[2];
  153.     int nfiles;
  154.  
  155. /*    fprintf(stderr, "searching_block( %d == %x )\n", block, block);  */
  156.     if (lseek(fd, hdr.block_table_offset + block * 4, SEEK_SET) < 0) {
  157.     fprintf(stderr, "lseek <1> failed: %s\n", strerror(errno));
  158.     exit(1);
  159.     }
  160.     Read(fd, &b, sizeof(b), 1);
  161.     if (block == (hdr.num_blocks - 1)) {
  162.         nfiles = hdr.num_files - b[0];
  163.     assert(nfiles > 0);
  164.     } else {
  165.         nfiles = b[1] - b[0];
  166.     assert(nfiles > 0);
  167.     }
  168.     p = malloc(nfiles * sizeof(*p));
  169.     if (lseek(fd, hdr.file_table_offset + (b[0] * 4), SEEK_SET) < 0) {
  170.     fprintf(stderr, "lseek <2> failed: %s\n", strerror(errno));
  171.     exit(1);
  172.     }
  173.     assert(lseek(fd, 0L, SEEK_CUR) ==
  174.            hdr.file_table_offset + (b[0] * 4));
  175.     Read(fd, p, nfiles * 4, 1);
  176.     for (rv = i = 0; i < nfiles; ++i) {
  177. #ifndef unix
  178.     char dir[3];
  179.  
  180.     sprintf(dir, "%c:", getdisk() + 'A');
  181.         rv += search_file(get_real_filename(dir, lookup_filename(p[i])));
  182. #else    
  183.         rv += search_file(lookup_filename(p[i]));
  184. #endif    
  185.     }
  186.     free(p);
  187.     return rv;
  188. }
  189.  
  190. static int
  191. search(unsigned long x) {
  192.     int rv;
  193.     unsigned char p[512];
  194.     int i, j, n, b;
  195.     long offset;
  196.  
  197.     rv = 0;
  198.     offset = x & 0xffffffL;
  199.     switch ((x >> 30) & 0x3) {
  200.  
  201.     case 0:
  202.         lseek(fd, offset, SEEK_SET);
  203.         Read(fd, p, sizeof(p), 0);
  204.         for (i = 0; i < hdr.num_blocks; ++i) {
  205.             if (p[i/8] & (1 << (i % 8))) {
  206.                 rv += search_block(i);
  207.             }
  208.         }
  209.         break;
  210.  
  211.     case 1:
  212.         rv = search_block(x & 0xfff);
  213.         break;
  214.  
  215.     case 2:
  216.         rv =  search_block(x & 0xfff);
  217.         rv += search_block((x >> 12) & 0xfff);
  218.         break;
  219.  
  220.     case 3:
  221.  
  222.         lseek(fd, offset, SEEK_SET);
  223.         Read(fd, p, sizeof(p), 0);
  224.         j = 0;
  225.         n = p[j++];
  226.         n += ((p[j] & 0x0f) << 8);
  227.         for (i = 1; i < n + 1; ++i) {
  228.             if (i & 1) {
  229.                 b = (p[j++] & 0xf0) >> 4;
  230.                 b += p[j++] << 4;
  231.             } else {
  232.                 b = p[j++];
  233.                 b += (p[j] & 0x0f) << 8;
  234.             }
  235.             rv += search_block(b);
  236.         }
  237.         break;
  238.     }
  239.     return rv;
  240. }
  241.  
  242. void
  243. main(int argc, char **argv) {
  244.     unsigned int len;
  245.     unsigned int match;
  246.     unsigned long h;
  247.     unsigned long x;
  248.     unsigned short i;
  249.  
  250.     if (argc != 2) {
  251.         fprintf(stderr,
  252.         "usage: lookup <word>\n"
  253.         "       Search a CDROM for all files containing\n"
  254.             "       the specified word.\n");
  255.         exit(1);
  256.     }
  257.     strcpy(word, argv[1]);
  258.     len = strlen(word);
  259.     for (i = 0; i < len; ++i) {
  260.         if (isupper(word[i])) {
  261.             word[i] = tolower(word[i]);
  262.         }
  263.     }
  264.     if ((fd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
  265.         fprintf(stderr, "cannot open %s: %s\n",
  266.         datafile, strerror(errno));
  267.         exit(1);
  268.     }
  269.     Read(fd, &hdr, sizeof(hdr), 1);
  270.     assert(hdr.header_size == sizeof(hdr));
  271.     assert(hdr.filesize == lseek(fd, 0L, SEEK_END));
  272.     h = hash2(word);
  273.     match = 0;
  274.     for (i = 0;; ++i) {
  275.         lseek(fd, (h * 4) + hdr.hash_table_offset, SEEK_SET);
  276.         Read(fd, &x, sizeof(x), 1);
  277.         if (x == 0) {
  278.             break;
  279.         }
  280.         if (((x >> 30) == 1 && ((x >> 12) & 0xffff) == rehash16) ||
  281.             ((x >> 30) != 1 && ((x >> 24) & 0x003f) == rehash6)) {
  282.             match = search(x);
  283.             break;
  284.         }
  285.         h = (h + rehash6 + i) % hdr.hash_prime;
  286.     }
  287.     if (match == 0) {
  288.         printf("sorry, no match\n");
  289.     }
  290.     exit(match == 0);
  291. }
  292.  
  293. static void
  294. Read(int fd, void *buf, int n, int swap) {
  295.  
  296.     assert(n > 0);
  297.     assert(swap == 0 || (n & 3) == 0);
  298.     if (read(fd, buf, n) < 0) {
  299.         fprintf(stderr, "read failed: %s\n", strerror(errno));
  300.         exit(1);
  301.     }
  302. #ifdef sparc
  303.     if (swap) {
  304.         int i;
  305.         unsigned char c;
  306.         unsigned char *p;
  307.  
  308.         p = buf;
  309.         for (i = 0; i < n; i += 4) {
  310.             c = p[i];
  311.             p[i] = p[i + 3];
  312.             p[i + 3] = c;
  313.             c = p[i + 1];
  314.             p[i + 1] = p[i + 2];
  315.             p[i + 2] = c;
  316.         }
  317.     }
  318. #endif
  319.     return;
  320. }
  321.  
  322. #ifdef sparc
  323. const char *
  324. strerror(error)
  325.     int error;
  326. {
  327.     static char defaultMsg[32];
  328.     extern int sys_nerr;
  329.     extern char *sys_errlist[];
  330.  
  331.     if ((error < sys_nerr) && (error > 0)) {
  332.         return sys_errlist[error];
  333.     }
  334.     (void) sprintf(defaultMsg, "unknown error (%d)", error);
  335.     return defaultMsg;
  336. }
  337. #endif
  338.  
  339.